package com.base.core.network.http.support;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.base.core.lang.StringUtils;
import com.base.core.constant.HttpConstants;
import com.base.core.exception.SimpleHttpException;
import com.base.core.network.http.Http;
import com.base.core.network.http.HttpHeader;
import com.base.core.network.http.ResponseEntity;
import com.base.core.utils.MapUtils;
import com.base.core.utils.UrlUtils;

import java.util.Map;

/**
 * <p>
 * 使用Hutool工具实现http功能
 * </p>
 *
 * @author becker
 * @date Created in 2019/12/24 19:08
 */
public class HttpHutool implements Http {
    private ResponseEntity exec(HttpRequest request) {
        request = request.timeout(HttpConstants.TIMEOUT);
        try (HttpResponse response = request.execute()) {
            if (!response.isOk()) {
                throw new SimpleHttpException("Unexpected code " + response);
            }
            ResponseEntity responseEntity = new ResponseEntity();
            responseEntity.setCode(response.getStatus());
            responseEntity.setMessage(null);
            responseEntity.setBody(response.body());
            return responseEntity;
        }
    }

    /**
     * GET 请求
     *
     * @param url URL
     * @return 结果
     */
    @Override
    public ResponseEntity get(String url) {
        return this.get(url, null, false);
    }

    /**
     * GET 请求
     *
     * @param url    URL
     * @param params 参数
     * @param encode 是否需要 url encode
     * @return 结果
     */
    @Override
    public ResponseEntity get(String url, Map<String, String> params, boolean encode) {
        return this.get(url, params, null, encode);
    }

    /**
     * GET 请求
     *
     * @param url    URL
     * @param params 参数
     * @param header 请求头
     * @param encode 是否需要 url encode
     * @return 结果
     */
    @Override
    public ResponseEntity get(String url, Map<String, String> params, HttpHeader header, boolean encode) {
        String baseUrl = StringUtils.appendIfNotContain(url, "?", "&");
        url = baseUrl + MapUtils.parseMapToString(params, encode);

        HttpRequest request = HttpRequest.get(url);

        if (header != null) {
            MapUtils.forEach(header.getHeaders(), request::header);
        }

        return exec(request);
    }

    /**
     * POST 请求
     *
     * @param url URL
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url) {
        HttpRequest request = HttpRequest.post(url);
        return this.exec(request);
    }

    /**
     * POST 请求
     *
     * @param url  URL
     * @param data JSON 参数
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, String data) {
        return this.post(url, data, null);
    }

    /**
     * POST 请求
     *
     * @param url    URL
     * @param data   JSON 参数
     * @param header 请求头
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, String data, HttpHeader header) {
        HttpRequest request = HttpRequest.post(url);

        if (StringUtils.isNotEmpty(data)) {
            request.body(data);
        }

        if (header != null) {
            MapUtils.forEach(header.getHeaders(), request::header);
        }
        return this.exec(request);
    }

    /**
     * POST 请求
     *
     * @param url    URL
     * @param params form 参数
     * @param encode 是否需要 url encode
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, Map<String, String> params, boolean encode) {
        return this.post(url, params, null, encode);
    }

    /**
     * POST 请求
     *
     * @param url    URL
     * @param params form 参数
     * @param header 请求头
     * @param encode 是否需要 url encode
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, Map<String, String> params, HttpHeader header, boolean encode) {
        HttpRequest request = HttpRequest.post(url);

        if (encode) {
            MapUtils.forEach(params, (k, v) -> request.form(k, UrlUtils.urlEncode(v)));
        } else {
            MapUtils.forEach(params, request::form);
        }

        if (header != null) {
            MapUtils.forEach(header.getHeaders(), request::header);
        }
        return this.exec(request);
    }
}
